<?php

/**
 * This is the model class for table "stock".
 *
 * The followings are the available columns in table 'stock':
 * @property integer $companyID
 * @property integer $exchangeID
 * @property integer $id
 * @property string $timestamp
 * @property integer $open
 * @property integer $high
 * @property integer $low
 * @property integer $close
 * @property integer $ref
 * @property integer $avg
 * @property integer $ceiling
 * @property integer $floor
 * @property integer $volumeKhopLenh
 * @property integer $volumeAgreement
 * @property integer $valueKhopLenh
 * @property integer $valueAgreement
 *
 * The followings are the available model relations:
 * @property Company $company
 */
class Stock extends CActiveRecord {

    public $file;
    public $fileDir;

    /**
     * Returns the static model of the specified AR class.
     * @return Stock the static model class
     */
    public static function model($className=__CLASS__) {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName() {
        return 'stock';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules() {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('timestamp, companyID, exchangeID', 'required'),
            array('companyID, exchangeID, open, high, low, close, ref, avg, ceiling, floor, volumeKhopLenh, volumeAgreement, valueKhopLenh, valueAgreement', 'numerical'),
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('companyID, exchangeID, id, timestamp,  open, high, low, close, ref, avg, ceiling, floor, volumeKhopLenh, volumeAgreement, valueKhopLenh, valueAgreement', 'safe', 'on' => 'search'),
                //array('file', 'file', 'types' => 'csv'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations() {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'company' => array(self::BELONGS_TO, 'Company', 'companyID'),
            'exchange' => array(self::BELONGS_TO, 'Exchanges', 'exchangeID'),
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels() {
        return array(
            'companyID' => 'Ticker',
            'exchangeID' => 'Exchange',
            'id' => 'ID',
            'timestamp' => 'Date',
            'open' => 'Open',
            'high' => 'High',
            'low' => 'Low',
            'close' => 'Close',
            'ref' => 'Ref',
            'avg' => 'Avg',
            'ceiling' => 'Ceiling',
            'floor' => 'Floor',
            'volumeKhopLenh' => 'Matched Volume',
            'volumeAgreement' => 'Volume Agreement',
            'valueKhopLenh' => 'Matched Value',
            'valueAgreement' => 'Value Agreement',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.
     */
    public function search() {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria = new CDbCriteria;
        $backup = $this->timestamp;

        if (preg_match('/[0-3]\d\/[01]\d\/\d{4}/', $this->timestamp)) {
            $this->timestamp = Stock::uk_date_to_mysql_date($this->timestamp);
        }
        $criteria->order = "timestamp desc";
        $criteria->compare('exchangeID', $this->exchangeID);
        $criteria->compare('companyID', $this->companyID);
        $criteria->compare('id', $this->id);
        $criteria->compare('timestamp', $this->timestamp, true);
        $criteria->compare('open', $this->open);
        $criteria->compare('high', $this->high);
        $criteria->compare('low', $this->low);
        $criteria->compare('close', $this->close);
        $criteria->compare('ref', $this->ref);
        $criteria->compare('avg', $this->avg);
        $criteria->compare('ceiling', $this->ceiling);
        $criteria->compare('floor', $this->floor);
        $criteria->compare('volumeKhopLenh', $this->volumeKhopLenh);
        $criteria->compare('volumeAgreement', $this->volumeAgreement);
        $criteria->compare('valueKhopLenh', $this->valueKhopLenh);
        $criteria->compare('valueAgreement', $this->valueAgreement);

        $result = new CActiveDataProvider($this, array(
                    'criteria' => $criteria,
                    'pagination' => array('pageSize' => 20), //TODO NN: Make this as an `app params`
                ));
        $this->timestamp = $backup;
        return $result;
    }

    function replaceString($string) {
        $string = str_replace(":", "%3A", $string);
        $string = str_replace("/", "%2F", $string);
        $string = str_replace("=", "%3D", $string);
        $string = str_replace("[", "%5B", $string);
        $string = str_replace("@", "%40", $string);
        $string = str_replace("]", "%5D", $string);
        $string = str_replace("[", "%5B", $string);
        $string = str_replace(" ", "%20", $string);
        $string = str_replace("?", "%3F", $string);
        $string = str_replace("&", "%26", $string);
        $string = str_replace("amp;", "", $string);
        return $string;
    }

    function remoreString($string) {
        $string = str_replace(",", "", $string);
        $string = str_replace("</p>", "", $string);
        $string = str_replace("<p>", "", $string);
        return $string;
    }

    function saveStock($v1, $v2, $v18, $v3, $v4, $v5, $v6, $v7, $v8, $v9, $v10, $v13, $v14, $v16, $v17) {
        $model = new Stock();
        $model->timestamp = $v1;
        $model->companyID = $v2;
        $model->ref = $v3;
        $model->ceiling = $v4;
        $model->floor = $v5;
        $model->open = $v6;
        $model->close = $v7;
        $model->high = $v8;
        $model->low = $v9;
        $model->avg = $v10;
        $model->volumeKhopLenh = $v13;
        $model->volumeAgreement = $v14;
        $model->valueKhopLenh = $v16;
        $model->valueAgreement = $v17;
        $model->exchangeID = $v18;
        $model->save();
    }

    public function getAllCompany($custom = false) {
        $list = Company::model()->findAll(array('order' => 'ticket ASC'));
        $data = array();
        if ($custom != false)
            $data[0] = $custom;
        foreach ($list as $com) {
            $data[$com->id] = $com->ticket;
        }
        return $data;
    }

    public function getAllExchanges($custom = false) {
        $list = Exchanges::model()->findAll(array('order' => 'name ASC'));
        $data = array();
        if ($custom != false)
            $data[0] = $custom;
        foreach ($list as $com) {
            $data[$com->id] = $com->name;
        }
        return $data;
    }

    public function searchForValidation($from, $to, $offset = NULL, $returnWrongData = false) {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.

        $criteria = new CDbCriteria;
        
        $hnx = Exchanges::model()->find("name = 'HNX'");
        
        if ($returnWrongData) {
            if(count($hnx) != 0) {
                $criteria->addCondition("avg <= 0 and exchangeiD = ". $hnx->id, "OR");
            }
            $criteria->addCondition("open <= 0", "OR");
            $criteria->addCondition("high <= 0", "OR");
            $criteria->addCondition("close <= 0", "OR");
            $criteria->addCondition("low <= 0", "OR");
            $criteria->addCondition("ceiling <= 0", "OR");
            $criteria->addCondition("floor <= 0", "OR");
            $criteria->addCondition("ref <= 0", "OR");

            $criteria->addCondition("open > ceiling", "OR");
            $criteria->addCondition("open < floor", "OR");

            $criteria->addCondition("close > ceiling", "OR");
            $criteria->addCondition("close < floor", "OR");

            $criteria->addCondition("high > ceiling", "OR");
            $criteria->addCondition("high < floor", "OR");

            $criteria->addCondition("low > ceiling", "OR");
            $criteria->addCondition("low < floor", "OR");

            $criteria->addCondition("open > high", "OR");
            $criteria->addCondition("open < floor", "OR");

            $criteria->addCondition("close > high", "OR");
            $criteria->addCondition("close < floor", "OR");
            
            $criteria->addCondition("timestamp < '2000-07-28'", "OR");
        }
        if (!$offset)
            $criteria->offset = $offset;
        $criteria->order = "timestamp desc";
        
        if ($this->companyID != 0)
            $criteria->compare('companyID', $this->companyID);
        if ($from != '' || $to != '') {
            if ($to == '' && $from != '') {
                $x = Stock::uk_date_to_mysql_date($from);
                $criteria->addCondition("timestamp >= '$x'");
            } elseif ($to != '' && $from == '') {
                $x = Stock::uk_date_to_mysql_date($to);
                $criteria->addCondition("timestamp <= '$x'");
            } else {
                $y = Stock::uk_date_to_mysql_date($to);
                $criteria->addCondition("timestamp BETWEEN '$x' AND '$y'");
            }
        }
        return new CActiveDataProvider($this, array(
                    'criteria' => $criteria,
                    'pagination' => array('pageSize' => 20), //TODO NN: Make this as an `app params`
                ));
    }

    public static function uk_date_to_mysql_date($date) {
        $date_year = substr($date, 6, 4);
        $date_month = substr($date, 3, 2);
        $date_day = substr($date, 0, 2);

        $date = date("Y-m-d", mktime(0, 0, 0, $date_month, $date_day, $date_year));
        return $date;
    }

    public static function validateData($data) {
        $result = array(
            'id' => 0,
            'exchangeID' => 0,
            'companyID' => 0,
            'timestamp' => 0,
            'open' => 0,
            'close' => 0,
            'high' => 0,
            'low' => 0,
            'ref' => 0,
            'avg' => 0,
            'ceiling' => 0,
            'floor' => 0,
            'volumeKhopLenh' => 0,
            'volumeAgreement' => 0,
            'valueKhopLenh' => 0,
            'valueAgreement' => 0,
        );
        
        $hnx = Exchanges::model()->find("name = 'HNX'");
        if(count($hnx) != 0) {
           if($data->exchangeID == $hnx->id && $data->avg <= 0) {
               $result['avg'] = 1;
           }
        }
        
        $limitDate = strtotime("2000-07-28 00:00:00");
        $date = strtotime($data->timestamp);
        if($date < $limitDate)
            $result['timestamp'] = 1;
        
        //If any important column <= 0, skip checking the relationship between columns
        if ($data->open <= 0 || $data->close <= 0 || $data->high <= 0 || $data->low <= 0 || $data->ceiling <= 0 || $data->floor <= 0 || $data->ref <= 0) {
            $result['open'] = ($data->open <= 0) ? 1 : 0;
            $result['close'] = ($data->close <= 0) ? 1 : 0;
            $result['high'] = ($data->high <= 0) ? 1 : 0;
            $result['low'] = ($data->low <= 0) ? 1 : 0;
            $result['ceiling'] = ($data->ceiling <= 0) ? 1 : 0;
            $result['floor'] = ($data->floor <= 0) ? 1 : 0;
            $result['ref'] = ($data->ref <= 0) ? 1 : 0;
        } else {
            //Validate Open value: ceiling > open > floor
            if (($data->ceiling >= $data->open) && ($data->open >= $data->floor ) && ($data->open >= $data->low ) && ($data->open <= $data->high ))
                $result['open'] = 0;
            else {
                $result['open'] = 1;
            }

            //Validate Close value: ceiling > close > floor
            if (($data->ceiling >= $data->close) && ($data->close >= $data->floor ) && ($data->close >= $data->low ) && ($data->close <= $data->high ))
                $result['close'] = 0;
            else {
                $result['close'] = 1;
            }

            //Validate High value: ceiling > High > floor and max(o, c, h, l) == high
            if (($data->ceiling >= $data->high) && ($data->high >= $data->floor ))
                $result['high'] = 0;
            else {
                $result['high'] = 1;
            }

            //Validate High value: ceiling > low > floor and min(o, c, h, l) == low
            if (($data->ceiling >= $data->low) && ($data->low >= $data->floor ))
                $result['low'] = 0;
            else {
                $result['low'] = 1;
            }
        }
        return $result;
    }

    function standard_deviation($aValues, $bSample = false) {
        $fMean = array_sum($aValues) / count($aValues);
        $fVariance = 0.0;
        foreach ($aValues as $i) {
            $fVariance += pow($i - $fMean, 2);
        }
		if(count($aValues)-1!=0) 
        $fVariance /= ( $bSample ? count($aValues) - 1 : count($aValues) );
		else $fVariance /= count($aValues);
        return (float) sqrt($fVariance);
    }

    function Correlation($arr1, $arr2) {
        $correlation = 0;

        $k = $this->SumProductMeanDeviation($arr1, $arr2);
        $ssmd1 = $this->SumSquareMeanDeviation($arr1);
        $ssmd2 = $this->SumSquareMeanDeviation($arr2);

        $product = $ssmd1 * $ssmd2;

        $res = sqrt($product);

        $correlation = $k / $res;

        return $correlation;
    }

    function SumProductMeanDeviation($arr1, $arr2) {
        $sum = 0;

        $num = count($arr1);
		$num2 = count ($arr2);
		if($num>$num2) $num = $num2;

        for ($i = 0; $i < $num; $i++) {
            $sum = $sum + $this->ProductMeanDeviation($arr1, $arr2, $i);
        }

        return $sum;
    }

    function ProductMeanDeviation($arr1, $arr2, $item) {
        return ($this->MeanDeviation($arr1, $item) * $this->MeanDeviation($arr2, $item));
    }

    function SumSquareMeanDeviation($arr) {
        $sum = 0;

        $num = count($arr);

        for ($i = 0; $i < $num; $i++) {
            $sum = $sum + $this->SquareMeanDeviation($arr, $i);
        }

        return $sum;
    }

    function SquareMeanDeviation($arr, $item) {
        return $this->MeanDeviation($arr, $item) * $this->MeanDeviation($arr, $item);
    }

    function SumMeanDeviation($arr) {
        $sum = 0;

        $num = count($arr);

        for ($i = 0; $i < $num; $i++) {
            $sum = $sum + $this->MeanDeviation($arr, $i);
        }

        return $sum;
    }

    function MeanDeviation($arr, $item) {
        $average = $this->Average($arr);
		//if($item>=count($arr)) return $arr[count($arr)-1] - $average;
        //if($item==0) return $arr[$item] - $average;
		return $arr[$item] - $average;
    }

    function Average($arr) {
        $sum = $this->Sum($arr);
        $num = count($arr);

        return $sum / $num;
    }

    function Sum($arr) {
        return array_sum($arr);
    }

    public function findStockID($stock) {
        // file chua ma chung khoan tu server fpt
        $data = file_get_contents('http://priceboard.fpts.com.vn/user/stock/_/_co.js');
        $pieces = explode(";", $data);
        $data1 = explode(",", $pieces[0]);
        $data2 = explode(",", $pieces[1]);
        $data = file_get_contents('http://priceboard.fpts.com.vn/user/stock/_/_upcom.js');
        $pieces = explode(";", $data);
        $data3 = explode(",", $pieces[0]);
        // if($stock=='AAA') return "HOSE";
        $count = 1;
        foreach ($data1 as $temp) {
            $temp = str_replace("\"", "", $temp);
            $temp = str_replace(")", "", $temp);
            if ($count != 1) {
                if ($temp == $stock)
                    return "HOSE";
            } else {
                $temp_data = explode("(", $temp);
                if ($temp_data[1] == $stock)
                    return "HOSE";
            }
            $count++;
        }

        $count = 1;
        foreach ($data2 as $temp) {
            $temp = str_replace("\"", "", $temp);
            $temp = str_replace(")", "", $temp);
            if ($count != 1) {
                if ($temp == $stock)
                    return "HNX";
            } else {
                $temp_data = explode("(", $temp);
                if ($temp_data[1] == $stock)
                    return "HNX";
            }
            $count++;
        }

        $count = 1;
        foreach ($data3 as $temp) {
            $temp = str_replace("\"", "", $temp);
            $temp = str_replace(")", "", $temp);
            if ($count != 1) {
                if ($temp == $stock)
                    return "UPCOM";
            } else {
                $temp_data = explode("(", $temp);
                if ($temp_data[1] == $stock)
                    return "UPCOM";
            }
            $count++;
        }
        return "HOSE";
    }
    
    public function getStockOptions() {
        $accTypeList = Stock::model()->findAll(); 
        $arrAcc = array();
        foreach ($accTypeList as $acc) {
            $arrAcc[$acc->id] = $acc->nameType;
        }
        return $arrAcc;
    }
    
    public function getCompanyOptions() {
        $accTypeList = Company::model()->findAll(); 
        $arrAcc = array();
        $temp = "";
        foreach ($accTypeList as $acc) {
            $temp .= "<option value=\"".$acc->ticket."\">".$acc->ticket."</option>"; 
            //$arrAcc[$acc->id] = $acc->nameType;
        }
        return $temp;
    }

}
